<template>
  <div class="record-operate-container">
    <audio v-if="audioInfo.mediaUrl" class="audio" controls :src="audioInfo.mediaUrl"></audio>
    <div v-else-if="recognizing" class="record-button" @click="recordOperate">
      <span class="identify">音色识别中...</span>
    </div>
    <div v-else class="record-button" @click="recordOperate">
      {{ isRecording ? '点击结束' : '点击开始录制' }}
      <span v-if="isRecording" class="time"
        >00:{{ recordTime > 9 ? recordTime : `0${recordTime}` }}</span
      >
    </div>

    <div class="tip">* 录制声音用来区分角色对话</div>
  </div>
</template>

<script setup lang="ts">
import { FFmpeg } from '@ffmpeg/ffmpeg';
import type { LogEvent } from '@ffmpeg/ffmpeg/dist/esm/types';
import { fetchFile, toBlobURL } from '@ffmpeg/util';

const ffmpeg = new FFmpeg() as any;

let mediaRecorder: MediaRecorder;
let recordedChunks: Blob[] = [];

const isRecording = ref(false);
const recordTime = ref(0);
const audioInfo = ref({
  featureId: '',
  mediaId: 0,
  mediaUrl: ''
});
const recognizing = ref(false);

const beforeStart = () => {
  recordedChunks = [];
  audioInfo.value = {
    featureId: '',
    mediaId: 0,
    mediaUrl: ''
  };
  recordTime.value = 0;
};
let startTimeStamp = 0;
let endTimeStamp = 0;

const startRecord = async () => {
  navigator.mediaDevices
    .getUserMedia({ audio: true })
    .then((stream) => {
      mediaRecorder = new MediaRecorder(stream);
      beforeStart();
      mediaRecorder.start();
      startTimeStamp = Date.now();
      isRecording.value = true;
      setTimeout(RecordTiming, 1000);

      mediaRecorder.addEventListener('dataavailable', (event) => {
        if (event.data.size > 0) {
          recordedChunks.push(event.data);
        }
      });

      mediaRecorder.addEventListener('stop', async () => {
        endTimeStamp = Date.now();
        recognizing.value = true;
        isRecording.value = false;
        const audioBlob = new Blob(recordedChunks, { type: 'audio/webm' });
        const tracks = stream.getTracks();
        tracks.forEach((track) => track.stop());
        // const audioBuffer = await audioBlob.arrayBuffer();
        // const uint8Array = new Uint8Array(audioBuffer);
        transcode(audioBlob);
      });
    })
    .catch((error) => {
      console.error('Error accessing microphone:', error);
    });
};
const RecordTiming = () => {
  if (isRecording.value) {
    if (recordTime.value > 59) {
      mediaRecorder.stop();
      return;
    }
    recordTime.value++;
    setTimeout(RecordTiming, 1000);
  }
};
const stopRecording = () => {
  mediaRecorder.stop();
};
const recordOperate = () => {
  if (isRecording.value) {
    stopRecording();
    return;
  }
  startRecord();
};

const baseURL = 'https://unpkg.com/@ffmpeg/core-mt@0.12.5/dist/esm';
const transcode = async (u: Blob) => {
  ffmpeg.on('log', ({ message: msg }: LogEvent) => {
    console.log('%c 🍈 msg: ', 'font-size:20px;background-color: #3F7CFF;color:#fff;', msg);
  });
  await ffmpeg.load({
    coreURL: await toBlobURL(`${baseURL}/ffmpeg-core.js`, 'text/javascript'),
    wasmURL: await toBlobURL(`${baseURL}/ffmpeg-core.wasm`, 'application/wasm'),
    workerURL: await toBlobURL(`${baseURL}/ffmpeg-core.worker.js`, 'text/javascript')
  });
  await ffmpeg.writeFile('input.webm', await fetchFile(u));
  await ffmpeg.exec('-i', 'input.webm', 'output.mp3');
  const data = await ffmpeg.readFile('output.mp3');
  const audioBlob = new Blob([data.buffer], { type: 'audio/mp3' });
  const audioUrl = URL.createObjectURL(audioBlob);
  audioInfo.value.mediaUrl = audioUrl;
};
</script>

<style lang="less" scoped>
.record-operate-container {
  padding: 200px;
  margin: 0 auto;
  width: fit-content;
  .record-button {
    width: fit-content;
    border-radius: 18px;
    border: 1px solid #dce0e5;
    background: #fff;
    box-shadow: 0px 4px 12px 0px rgba(236, 236, 236, 0.5);
    color: #34363f;
    font-weight: 500;
    line-height: 24px;
    /* 171.429% */
    display: flex;
    align-items: center;
    gap: 6px;
    padding: 6px 14px 6px 10px;
    cursor: pointer;
    .time {
      margin-left: 8px;
      color: #34363f;
      font-size: 14px;
      font-weight: 400;
      line-height: 24px;
    }
    .identify {
      color: #5e6375;
      font-size: 12px;
      font-weight: 400;
      line-height: 18px;
    }
  }
  .tip {
    margin-top: 8px;
    color: #5e6375;
    font-size: 12px;
    font-weight: 400;
    line-height: 16px; /* 133.333% */
  }
}
</style>
